/**************************************************************************************
*
*	Copyright (C) 2009 - 2012 Brent Andrew O. Chua - See LICENSE.txt for more info.
*		
*	Filename	-	GraphicsPipeline.cpp
*
*	Comments	-	See GraphicsPipeline.h
*
**************************************************************************************/
#include "../Include/GraphicsPipeline.h"
#include "../Include/Renderer.h"
#include "../Include/Geometry.h"


namespace Pulse
{
	GraphicsPipeline::GraphicsPipeline( Renderer *pRenderer )
		: m_pRenderer( pRenderer )
	{
		PSX_ZeroMem( m_pStages, sizeof(m_pStages) );
		PSX_ZeroMem( m_pShaderStages, sizeof(m_pShaderStages) );
	}

	GraphicsPipeline::~GraphicsPipeline( void )
	{

	}

	void GraphicsPipeline::SetInputAssemblerStage( InputAssemblerStage *pStage )
	{
		m_pInputAssembler = pStage;
		SetStageRenderer( pStage );
	}

	void GraphicsPipeline::SetVertexShaderStage( VertexShaderStage *pStage )
	{
		m_pVertexShader = pStage;
		m_pShaderStages[EShader::VERTEX] = pStage;
		SetStageRenderer( pStage );
	}

	void GraphicsPipeline::SetPixelShaderStage( PixelShaderStage *pStage )
	{
		m_pPixelShader = pStage;
		m_pShaderStages[EShader::PIXEL] = pStage;
		SetStageRenderer( pStage );
	}

	void GraphicsPipeline::SetRasterizerStage( RasterizerStage *pStage )
	{
		m_pRasterizer = pStage;
		SetStageRenderer( pStage );
	}

	void GraphicsPipeline::SetOutputMergerStage( OutputMergerStage *pStage )
	{
		m_pOutputMerger = pStage;
		SetStageRenderer( pStage );
	}

	void GraphicsPipeline::SetComputeShaderStage( ComputeShaderStage *pStage )
	{
		m_pComputeShader = pStage;
		m_pShaderStages[EShader::COMPUTE] = pStage;
		SetStageRenderer( pStage );
	}

	void GraphicsPipeline::SetStageRenderer( IPipelineStage *pStage )
	{
		if ( pStage )
			pStage->SetRenderer( m_pRenderer );
	}

	void GraphicsPipeline::ClearStageStates( const BOOL bIA, const BOOL bVS, const BOOL bPS, const BOOL bRS, const BOOL bOM, const BOOL bCS )
	{
		if ( bIA )
		{
			m_pInputAssembler->ClearStates();
		}
		
		if ( bVS )
		{
			m_pVertexShader->ClearStates();
		}
		
		if ( bPS )
		{
			m_pPixelShader->ClearStates();
		}
		
		if ( bOM )
		{
			m_pOutputMerger->ClearStates();
		}

		if ( bCS )
		{
			m_pComputeShader->ClearStates();
		}
	}
	
	void GraphicsPipeline::ApplyStageStates( const BOOL bIA, const BOOL bVS, const BOOL bPS, const BOOL bRS, const BOOL bOM, const BOOL bCS )
	{
		if ( bIA )
		{
			m_pInputAssembler->BindStates();
		}
		
		if ( bVS )
		{
			m_pVertexShader->BindStates();
		}
		
		if ( bPS )
		{
			m_pPixelShader->BindStates();
		}
		
		if ( bOM )
		{
			m_pOutputMerger->BindStates();
		}

		if ( bCS)
		{
			m_pComputeShader->BindStates();
		}
	}

	void GraphicsPipeline::DrawIndexed( UINT indexCount, UINT startIndexLocation, INT baseVertexLocation )
	{
		m_pRenderer->DrawIndexed( indexCount, startIndexLocation, baseVertexLocation );
	}

	void GraphicsPipeline::Dispatch( UINT threadCountX, const UINT threadCountY, const UINT threadCountZ )
	{
		m_pRenderer->Dispatch( threadCountX, threadCountY, threadCountZ );
	}

	void GraphicsPipeline::BindStateChanges( void )
	{

	}

	/*void GraphicsPipeline::ClearStates( void )
	{
		for ( UINT i = 0; i < EPipelineStage::EnumCount; ++i )
		{
			if ( m_pStages[i] )
			{
				m_pStages[i]->ClearStates();
			}
		}
	}*/

}